/*
 *  Copyright (C) 2011  Clint Priest
 *
 *  This file is part of Snap Graph.
 *
 *  Snap Graph is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Snap Graph is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Snap Graph.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
 
var PlotScheme = Class.create( {
	initialize: function(PrimaryColor, Opacity) {
		this.PrimaryColor = PrimaryColor;
		this.Opacity = Opacity || 0.25;
		this.LineWidth = 1.25;

		this.BarWidth = 7;
	},
	/* Place holder class w/ data values at the moment */
	PrimaryColor: '',
} );

var GraphPlot = Class.create( {
	
	initialize: function(Graph, DataSelection, Scheme) {
		this.Graph = Graph;
		this.Paper = this.Graph.Paper;
		this.Scheme = Scheme;
		this.DataSelection = DataSelection;
		this.CreateElements(this.DataSelection.Coordinates);
		console.log(this.OnMouseOver.toString());
		this.AllElements.mouseover( this.OnMouseOver.bind(this));
		this.AllElements.mouseout( this.OnMouseOut.bind(this));
		 
	},
	CreateElements: function(Coordinates) {
		/* Should be implemented by subclasses */
		throw new Error('Not Implemented');
	},
	AdjustLayers: function() { },
	OnMouseOver: function(e) { },
	OnMouseOut: function(e) { },
} );

var LinePlot = Class.create( GraphPlot, {
	CreateElements: function(Coordinates) {
		if(this.AllElements)
			this.AllElements.remove();

		this.Coordinates = Coordinates;
		
		var Path = this.Coordinates.reduce( function( acc, xy ) {
//			this.Paper.circle(xy.x, xy.y, 2).attr( { fill: 'white' } );
			acc.push((acc.length == 0 ? 'M' : 'L') + xy.x + ',' + xy.y);
			return acc;
		}.bind(this), [ ]).join(' ');
		this.Line = this.Paper.path(Path).attr( { stroke: this.Scheme.PrimaryColor, 'stroke-width': this.Scheme.LineWidth } ).toFront();
		this.AllElements = this.Line;
	},
	AdjustLayers: function() {
		this.Line.toFront();
	},
	OnMouseOver: function(e) {
		this.Line.attr( { 'stroke-width': this.Scheme.LineWidth + 0.5 } );
	},
	OnMouseOut: function(e) {
		this.Line.attr( { 'stroke-width': this.Scheme.LineWidth } );
	},
});

var AreaPlot = Class.create( GraphPlot, {
	CreateElements: function(Coordinates) {
		if(this.AllElements)
			this.AllElements.remove();

		this.Coordinates = Coordinates;
		
		var Path = this.Coordinates.reduce( function( acc, xy ) {
//			this.Paper.circle(xy.x, xy.y, 2).attr( { fill: 'white' } );
			acc.push((acc.length == 0 ? 'M' : 'L') + xy.x + ',' + xy.y);
			return acc;
		}.bind(this), [ ]);
		this.Line = this.Paper.path(Path.join(' ')).attr( { stroke: this.Scheme.PrimaryColor, 'stroke-width': this.Scheme.LineWidth } );
		
		Path = Path.concat(
					'L' + this.Graph.PlotRect.left + ',' + this.Graph.PlotRect.bottom,
					'L' + this.Graph.PlotRect.right + ',' + this.Graph.PlotRect.bottom,
					'L' + Coordinates[0].x + ',' + Coordinates[0].y);
		this.Area = this.Paper.path(Path.join(' ')).attr( { fill: this.Scheme.PrimaryColor, 'fill-opacity': this.Scheme.Opacity } );
		this.AllElements = this.Paper.set(	this.Line, this.Area );
	},
	AdjustLayers: function() {
		this.Line.toFront();
		this.Area.insertAfter(this.Graph.Background);
	},
	OnMouseOver: function(e) {
		this.Line.attr( { 'stroke-width': this.Scheme.LineWidth + 0.5 } );
	},
	OnMouseOut: function(e) {
		this.Line.attr( { 'stroke-width': this.Scheme.LineWidth } );
	},
} );


var AverageBars = Class.create( GraphPlot, {
	initialize: function($super, Graph, DataSelection, Scheme) {
		this.Bars = [ ];
		$super(Graph, DataSelection, Scheme);
	},
	CreateElements: function(Coordinates) {
		if(this.AllElements)
			this.AllElements.remove();

		this.Bars = this.Paper.set();
		this.Coordinates = Coordinates;
		
		this.AvgY = this.Graph.VerticalAxes[this.DataSelection.VerticalAxisGroup].TranslateValue(new ValueSet(Object.values(this.DataSelection.Data)).Average);
		
		this.AvgLine = this.Paper.path( [
				'M' + this.Graph.PlotRect.left + ',' + this.AvgY,
				'L' + this.Graph.PlotRect.right + ',' + this.AvgY,
			].join(' ')
		).attr( { stroke: '#707070', 'stroke-width': 1 } );
		
		this.Coordinates.forEach( function( pt ) {
			this.CreateBar(pt);
		}, this );

		this.AllElements = this.Paper.set(	this.AvgLine, this.Bars );
	},
	CreateBar: function(pt) {
		this.Bars.push(
			this.Graph.Paper.rect(pt.x - (this.Scheme.BarWidth / 2), Math.min(pt.y, this.AvgY), this.Scheme.BarWidth, Math.max(pt.y, this.AvgY) - Math.min(pt.y, this.AvgY))
				.attr( { stroke: this.Scheme.PrimaryColor, 'stroke-width': .75, fill: this.Scheme.PrimaryColor, 'fill-opacity': 0.3 } )
		);
	},
	OnMouseOver: function(e) {
		this.Bars.attr( { 'stroke-width': 1.25 } );
	},
	OnMouseOut: function(e) {
		this.Bars.attr( { 'stroke-width': .75 } );
	},
} );